import sys
from sanic.response import json as json_res
from util.date_utils import timestamp
from urllib.parse import unquote
import base64
from random import sample
from decimal import Decimal, ROUND_HALF_UP

# 随机数基础字符串
RANDOM_BASE = "QWERTYUIOPLKJHGFDSAZXCVBNMqwertyuioplkjhgfdsazxcvbnm0987654321"

# API 签名使用的字符串
APISTR = 'CONSTLEVAR'

# 配置日志的记录，具体的记录的文件的日志，使用 supervisor 记录
log_config = {
    "version": 1,
    "disable_existing_loggers": False,
    "loggers": {
        "sanic.root": {
            "level": "INFO",
            "handlers": ["console"],
            "propagate": False
        },
        "sanic.error": {
            "level": "INFO",
            "handlers": ["error_console"],
            "propagate": False,
            "qualname": "sanic.error",
        },
        "sqlalchemy.engine.Engine": {
            "handlers": [],
            "propagate": False,
        },
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "generic",
            "stream": sys.stdout,
        },
        "error_console": {
            "class": "logging.StreamHandler",
            "formatter": "generic",
            "stream": sys.stderr,
        },
    },
    "formatters": {
        "generic": {
            "format": "[%(asctime)s] (%(name)s) [%(levelname)s] [%(lineno)d]: %(message)s",
            "class": "logging.Formatter",
        },
    },
    "root": {
        "handlers": ["console"],
        "level": "DEBUG"
    },
}


def jsonify(data=None, page_info=None, headers=None):
    """返回通用格式的数据，code, message, data

    Args:
        data (object|list): 返回的数据

    Returns:
        Response: sanic json response
    """
    r = {"code": 0, "message": "SUCCESS", "data": data}
    if data is not None:
        r["data"] = data
    if page_info is not None:
        r["pageInfo"] = page_info
    return json_res(r)


def is_blank(str, ignore_whitespace=True):
    """验证字符串是否为空

    Args:
        str (str): 待验证的字符串
        ignore_whitespace (bool, optional): 是否忽略空格(包括空白字符串以及[\\r\\t\\n]之类的制表符),
            默认为true

    Returns:
        bool: bool
    """
    if str is None:
        return True
    return len(str.strip() if ignore_whitespace is True else str) == 0


def is_not_blank(str, ignore_whitespace=True):
    """ 非空验证 """
    return is_blank(str, ignore_whitespace) is False


def dict_value(data: dict, key: str, default=None):
    """获取字典的某个key,如果key不存在则返回默认值

    Args:
        key (str): 需要获取的 key
        data (dict): 字典
        default (any, optional): 如果key不存在返回的默认值. Defaults to None.

    Returns:
        any: 获取到的key对应的值
    """
    return data[key] if key in data else default


def dict_has(data: dict, key: str):
    """验证字典是否包含某个 key, 有key且值不为None

    Args:
        data (dict): 字典
        key (str): 检查的key

    Returns:
        bool: 检查是否有key且值不为None
    """
    if key in data and data[key] is not None:
        return True
    return False


def dict_has_more(data: dict, keys):
    """检查字典是否包含多个key的值

    Args:
        data (dict): 字典
        keys (list|tuple): 要检查的key的列表

    Returns:
        bool: True - 包含所有的 key
    """
    is_has = True
    for key in keys:
        if not dict_has(data, key):
            is_has = False
            break
    return is_has


def randomStr(len=16):
    """随机字符串

    Args:
        len (int, optional): 生成多少位的随机字符串，默认为：16. Defaults to 16.

    Returns:
        str: 随机字符串
    """
    return "".join(sample(RANDOM_BASE, len))


def round_up(n: float, precision=".01"):
    """将数字四舍五入

    Args:
        n (float): 带舍入的数字
        precision (str, optional): 精度, 默认为小数点后2位. Defaults to ".01".

    Returns:
        float: 四舍五入后的数字
    """
    d = Decimal(f"{n}")
    return float(d.quantize(Decimal(precision), ROUND_HALF_UP))


def multiply(num1: str | float, num2: str | float, format="str", round_up=True, precision=".01"):
    """两数相乘

    Args:
        num1 (str | float): 第一个数
        num2 (str | float): 第二个数
        format (str, optional): 将结果进行转换返回, 允许的值有: str(字符串返回)、float(浮点数返回)、decimal. Defaults to "decimal".
        round_up (bool, optional): 是否将结果四舍五入
        precision (str | None, optional): 精度处理，例如：.01, .001……

    Returns:
        (str | float | Decimal): 返回乘积, 类型根据 format 值确定
    """
    d1 = Decimal(f"{num1}")
    d2 = Decimal(f"{num2}")
    d = d1 * d2
    if is_not_blank(precision):
        rounding = ROUND_HALF_UP if round_up else None
        d = d.quantize(Decimal(precision), rounding=rounding)
    if format == 'str':
        return str(d)
    elif format == 'float':
        return float(d)
    else:
        return d


def check_sign(t: str, sign: str):
    """验证签名

    Args:
        t (str): 时间戳
        sign (str): 签名

    Returns:
        bool: 签名是否正确
    """
    # 验证签名和请求时间戳，不能为空
    if is_blank(t) or is_blank(sign):
        return False
    # 验证请求时间戳跟当前时间不能超过5s
    curr_time = timestamp(None, 'ms')
    if curr_time - int(t) > 5000:
        return False
    # 解析请求 sign
    sign_t = sign[3:len(sign) - 4]
    ss = []
    for s in sign_t:
        si = APISTR.find(s)
        if si == -1:
            break
        ss.append(str(si))
    ss.reverse()
    # 验证签名是否正确
    return ''.join(ss) == t
